#include <cxxabi.h>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <utility>

enum class DataType {INT = 0, FLOAT, BOOL, PTR, DOUBLE, SIZE_T, UINT, UNREC};
using TypeInfo = std::pair<size_t, DataType>;

std::string extractFuncName(const std::string& decl) {
    // 步骤1：定位参数列表起始位置（忽略模板括号）
    size_t param_start = decl.find('(');
    if (param_start == std::string::npos) {
        return "";
    }

    // 步骤2：提取前缀部分并去除尾部空格
    std::string prefix = decl.substr(0, param_start);
    auto end_it = std::find_if_not(prefix.rbegin(), prefix.rend(), 
        [](char c) { return std::isspace(c); });
    prefix = (end_it == prefix.rend()) ? "" : prefix.substr(0, end_it.base() - prefix.begin());

    // 步骤3：从后向前查找函数名起始位置
    int bracket_count = 0;
    auto name_start = std::find_if(prefix.rbegin(), prefix.rend(), 
        [&](char c) {
            if (c == '>') bracket_count++;
            else if (c == '<' && bracket_count > 0) bracket_count--;
            return bracket_count == 0 && std::isspace(c);
        });

    // 步骤4：提取函数名部分
    return (name_start == prefix.rend()) 
        ? prefix 
        : std::string(name_start.base(), prefix.end());
}

// 辅助函数：去除字符串首尾空格
std::string trim(const std::string& str) {
    auto start = str.find_first_not_of(" ");
    auto end = str.find_last_not_of(" ");
    return (start == std::string::npos) ? "" : str.substr(start, end - start + 1);
}

// 主解析函数
std::vector<TypeInfo> parseFuncParameters(const std::string& demangled_decl) {
    std::vector<TypeInfo> result;
    
    // 查找参数列表的开始和结束位置
    size_t start_paren = demangled_decl.find('(');
    size_t end_paren = demangled_decl.rfind(')');
    
    if (start_paren == std::string::npos || end_paren == std::string::npos || 
        start_paren >= end_paren) {
        return result; // 无效的函数声明
    }
    
    // 提取参数列表子串
    std::string params_str = demangled_decl.substr(start_paren + 1, end_paren - start_paren - 1);
    
    // 使用字符串流分割参数
    std::istringstream iss(params_str);
    std::string type_str;
    size_t index = 0;
    
    while (std::getline(iss, type_str, ',')) {
        // 去除首尾空格
        type_str = trim(type_str);
        if (type_str.empty()) continue;
        
        // 检查指针类型
        if (type_str.find('*') != std::string::npos) {
            result.emplace_back(index++, DataType::PTR);
            continue;
        }
        
        // 转换为小写以简化匹配
        std::transform(type_str.begin(), type_str.end(), type_str.begin(),
                       [](unsigned char c) { return std::tolower(c); });
        
        // 匹配基本类型
        if (type_str == "int" || type_str == "long" || type_str == "signed") {
            result.emplace_back(index++, DataType::INT);
        } else if (type_str == "float") {
            result.emplace_back(index++, DataType::FLOAT);
        } else if (type_str == "double") {
            result.emplace_back(index++, DataType::DOUBLE);
        } else if (type_str == "bool") {
            result.emplace_back(index++, DataType::BOOL);
        }else if (type_str == "unsigned int" || type_str == "unsigned" || type_str == "uint32_t") {
            result.emplace_back(index++, DataType::UINT);
        } else if (type_str == "size_t" || type_str == "uint64_t") {
            result.emplace_back(index++, DataType::SIZE_T);
        } else {
            result.emplace_back(index++, DataType::UNREC);
        }
    }
    
    return result;
}

std::string DataTypeToStr(DataType dataType){
    std::string dataTypeStr;
    switch (dataType) {
        case DataType::INT:
            dataTypeStr = "int";;
            break;
        case DataType::FLOAT:
            dataTypeStr = "float";
            break;
        case DataType::BOOL:
            dataTypeStr = "bool";
            break;
        case DataType::PTR:
            dataTypeStr = "ptr";
            break;
        case DataType::DOUBLE:
            dataTypeStr = "double";
            break;
        case DataType::SIZE_T:
            dataTypeStr = "size_t";
            break;
        case DataType::UINT:
            dataTypeStr = "uint";
            break;
        default:
            dataTypeStr = "??";
            break;
    }
    return dataTypeStr;
}

int main() {
    std::vector<std::string> mangled_names = {
        "_Z13decode_kernelI13__nv_bfloat16Li8EEvPKT_PS1_S4_S4_PKiS6_S6_S6_S6_PKfS8_iiiiijib"    
    };
    for(auto mangled: mangled_names){
        int status = 0;
        std::string demangled = abi::__cxa_demangle(mangled.c_str(), nullptr, nullptr, &status);
        if (status == 0) {
            std::cout << demangled << std::endl;  // 输出: add(int, int)
        }
        std::cout << extractFuncName(demangled) << std::endl;
        auto t_vec = parseFuncParameters(demangled);
        for(auto &t_info: t_vec){
            std::cout << t_info.first << "," << DataTypeToStr(t_info.second) << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}